﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text; 
using ADV_Evaluator.Command;
using SD = System.Drawing;
using YD = Yanesdk.Draw;


namespace ADV_Evaluator {

    /// <summary>
    /// ゲーム内で使用するウィンドウの基底クラス
    /// </summary>
    public class Window_Base : IDisposable{

        protected const int Margin = 5;
        protected const int Padding = 5;

		private bool enable;
        protected int x;
        protected int y;
        protected int width;
        protected int height;
        protected byte alpha;
        protected YD.GlTexture texture;
        protected Bitmap bitmap;
        protected SD.Font font;
        protected SD.Brush textBrush;
        private LinearGradientBrush skinBrush;
        private Color skinColor1, skinColor2;
        private LinearGradientMode gradientMode;
        private Pen borderPen;
        private bool visible;
        private bool borderVisible;
        private Rectangle skinRect;
        protected Rectangle contentRect;

		/// <summary>
		/// 活性・非活性
		/// </summary>
		public bool Enable
		{
			get { return enable; }
			set { enable = value; }
		}
		
		/// <summary>
        /// X座標
        /// </summary>
        public int X { 
            get { return x; } 
            set { x = value; }
        }
        /// <summary>
        /// Y座標
        /// </summary>
        public int Y { 
            get { return y; } 
            set { y = value; }
        }
        /// <summary>
        /// 幅
        /// </summary>
        public int Width { 
            get { return width; }
            set { Resize(value, height); }
        }
        /// <summary>
        /// 高さ
        /// </summary>
        public int Height { 
            get { return height; }
            set { Resize(width, value); }
        }
        /// <summary>
        /// 矩形
        /// </summary>
        public Rectangle Rect {
            get { return new Rectangle(x, y, width, height); }
        }
        /// <summary>
        /// 枠線の幅
        /// </summary>
        public int BorderWidth {
            get { return (int)borderPen.Width; }
            set { borderPen.Width = value; SetRect(); }
        }
        /// <summary>
        /// 枠線の色
        /// </summary>
        public Color BorderColor {
            get { return borderPen.Color; }
            set { borderPen.Color = value; }
        }
        /// <summary>
        /// ウィンドウの可視状態
        /// </summary>
        public bool Visible {
            get { return visible; }
            set { visible = value; }
        }
        /// <summary>
        /// アルファ値
        /// </summary>
        public byte Alpha {
            get { return alpha; }
            set { alpha = value; }
        }
        /// <summary>
        /// 枠線の可視状態
        /// </summary>
        public bool BorderVisible {
            get { return borderVisible; }
            set { borderVisible = value; }
        }
        /// <summary>
        /// メッセージの表示に用いるフォント
        /// </summary>
        public SD.Font Font {
            get { return font; }
            set { font = value; }
        }
        /// <summary>
        /// スキン色１
        /// </summary>
        public SD.Color SkinColor1 {
            get { return skinColor1; }
            set { skinColor1 = value; SetSkinBrush();  }
        }
        /// <summary>
        /// スキン色２
        /// </summary>
        public SD.Color SkinColor2 {
            get { return skinColor2; }
            set { skinColor2 = value; SetSkinBrush();  }
        }
        /// <summary>
        /// グラデーションの方向
        /// </summary>
        public LinearGradientMode GradientMode {
            get { return gradientMode; }
            set { gradientMode = value; SetSkinBrush(); }
        }
        /// <summary>
        /// ビットマップ
        /// </summary>
        public Bitmap Bitmap { 
            get { return bitmap; }
        }
        /// <summary>
        /// テクスチャ
        /// </summary>
        public YD.GlTexture Texture { 
            get { return texture; }
        }


        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="width">幅</param>
        /// <param name="height">高さ</param>
        public Window_Base(int width, int height) {
			enable = true;
            x = 0;
            y = 0;
            this.width = width;
            this.height = height;
            borderPen = new Pen(Color.White, 3);
            font = new SD.Font(FontFamily.GenericSerif, 18);
            textBrush = Brushes.White;
            alpha = 255;
            bitmap = new Bitmap(width, height);
            texture = new YD.GlTexture();
            SetRect();
            skinColor1 = Color.FromArgb(160, Color.Navy);
            skinColor2 = Color.FromArgb(160, Color.RoyalBlue);
            gradientMode = LinearGradientMode.ForwardDiagonal;
            visible = true;
            borderVisible = true;
            SetSkinBrush();            
        }
        /// <summary>
        /// 座標を指定したコンストラクタ
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public Window_Base(int x, int y, int width, int height) : this(width, height) {
            this.x = x;
            this.y = y;
        }

        /// <summary>
        /// 文章表示オプションの属性の値を全てセット
        /// </summary>
        /// <param name="attr"></param>
        /// <param name="screenHeight">画面の高さ</param>
        public virtual void SetParams(MessageOptionParams param) {
            this.Visible = param.Visible;
            this.BorderVisible = param.BorderVisible;
            this.BorderColor = param.BorderColor;
            this.SkinColor1 = param.SkinColor1;
            this.SkinColor2 = param.SkinColor2;
            this.Font = new SD.Font(FontFamily.GenericSerif, param.FontSize);
            this.GradientMode = param.GradientMode;
        }

        /// <summary>
        /// プロパティの値を文章表示オプションの構造体にして返す
        /// </summary>
        /// <returns></returns>
        public virtual MessageOptionParams GetParams() {
            MessageOptionParams param = new MessageOptionParams();
            param.WindowAlign = WindowAlign.Bottom;
            param.TextHorizontalAlign = StringAlignment.Near;
            param.TextVerticalAlign = StringAlignment.Near;
            param.Visible = this.Visible;
            param.BorderVisible = this.BorderVisible;
            param.BorderColor = this.BorderColor;
            param.SkinColor1 = this.SkinColor1;
            param.SkinColor2 = this.SkinColor2;
            param.FontSize = this.Font.Size;
            param.GradientMode = this.GradientMode;
            return param;
        }

        /// <summary>
        /// ウィンドウの枠線とスキンを描画
        /// </summary>
        protected void DrawBackground() {
            using (Graphics graphics = Graphics.FromImage(bitmap)) {
                graphics.Clear(Color.Transparent);
                graphics.FillRectangle(skinBrush, skinRect);
                if (borderVisible) {
                    graphics.DrawRectangle(borderPen, skinRect);
                }
            }
        }

        /// <summary>
        /// 再描画し、テクスチャへセット
        /// </summary>
        public virtual void Refresh() {
            DrawBackground();
            texture.SetBitmap(bitmap);
        }

        /// <summary>
        /// スクリーンへ転送
        /// </summary>
        /// <param name="system"></param>
        public virtual void Update(GameSystem system) {
            if (visible) {
                system.Screen.SetColor(255, 255, 255, alpha);
                system.Screen.Blt(texture, x, y);
                system.Screen.ResetColor();
            }
        }

        /// <summary>
        /// サイズを変更
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void Resize(int width, int height) {
            this.width = width;
            this.height = height;
            if (bitmap != null) {
                bitmap.Dispose();
            }
            bitmap = new Bitmap(width, height);
            SetRect();
            SetSkinBrush();
            Refresh();
        }

        /// <summary>
        /// 描画用矩形をセット
        /// </summary>
        protected void SetRect(){
            skinRect = new Rectangle(Margin, Margin, width-(Margin*2), height-(Margin*2));
            contentRect = new Rectangle(
                Margin + (int)borderPen.Width + Padding,
                Margin + (int)borderPen.Width + Padding,
                width - (Margin * 2) - ((int)borderPen.Width * 2) - (Padding * 2),
                height - (Margin * 2) - ((int)borderPen.Width * 2) - (Padding * 2)
            );
        }

        /// <summary>
        /// 背景描画用ブラシをセット
        /// </summary>
        protected void SetSkinBrush(){
            skinBrush = new LinearGradientBrush(skinRect, skinColor1, skinColor2, gradientMode);
            skinBrush.GammaCorrection = true;
        }

        /// <summary>
        /// 解放
        /// </summary>
        public virtual void Dispose() {
            bitmap.Dispose();
            texture.Dispose();
            font.Dispose();
            skinBrush.Dispose();
        }

    }
}
